package com.ruoyi.common.utils.file;

import com.ruoyi.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 文件下载诊断工具类
 * 专门用于调试和分析特殊的文件服务接口
 *
 * @author llm
 */
@Slf4j
public class FileDownloadDiagnostics {

    /**
     * 诊断文件下载URL的详细信息
     *
     * @param fileUrl 要诊断的文件URL
     * @return 诊断结果
     */
    public static DiagnosticResult diagnoseUrl(String fileUrl) {
        DiagnosticResult result = new DiagnosticResult();
        result.setOriginalUrl(fileUrl);

        try {
            // 1. URL清理和解析
            String cleanUrl = cleanUrl(fileUrl);
            result.setCleanedUrl(cleanUrl);

            URL url = new URL(cleanUrl);
            result.setHost(url.getHost());
            result.setPort(url.getPort());
            result.setPath(url.getPath());
            result.setQuery(url.getQuery());

            // 2. 尝试多种User-Agent
            String[] userAgents = {
                    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
                    "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0",
                    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
            };

            // 3. 尝试不同的请求方法
            for (String userAgent : userAgents) {
                DiagnosticAttempt attempt = testDownload(cleanUrl, userAgent, "GET");
                result.addAttempt(attempt);

                if (attempt.isSuccess()) {
                    result.setRecommendedUserAgent(userAgent);
                    break;
                }
            }

            // 4. 如果GET失败，尝试POST
            if (!result.hasSuccessfulAttempt()) {
                DiagnosticAttempt postAttempt = testDownload(cleanUrl, userAgents[0], "POST");
                result.addAttempt(postAttempt);
            }

            // 5. 尝试HEAD请求获取更多信息
            DiagnosticAttempt headAttempt = testDownload(cleanUrl, userAgents[0], "HEAD");
            result.addAttempt(headAttempt);

        } catch (Exception e) {
            result.setError("诊断过程中发生错误: " + e.getMessage());
            log.error("诊断URL失败: {}", fileUrl, e);
        }

        return result;
    }

    /**
     * 测试下载
     */
    private static DiagnosticAttempt testDownload(String url, String userAgent, String method) {
        DiagnosticAttempt attempt = new DiagnosticAttempt();
        attempt.setMethod(method);
        attempt.setUserAgent(userAgent);

        HttpURLConnection connection = null;
        try {
            URL urlObj = new URL(url);
            connection = (HttpURLConnection) urlObj.openConnection();

            // 设置请求方法和属性
            connection.setRequestMethod(method);
            connection.setConnectTimeout(10000);
            connection.setReadTimeout(30000);

            // 设置详细的请求头
            setupDetailedHeaders(connection, userAgent);

            // 记录请求头
            attempt.setRequestHeaders(getRequestHeaders(connection));

            // 发送请求
            long startTime = System.currentTimeMillis();
            int responseCode = connection.getResponseCode();
            long endTime = System.currentTimeMillis();

            attempt.setResponseCode(responseCode);
            attempt.setResponseTime(endTime - startTime);
            attempt.setResponseMessage(connection.getResponseMessage());

            // 记录响应头 - 过滤null key
            Map<String, List<String>> rawHeaders = connection.getHeaderFields();
            Map<String, List<String>> cleanHeaders = new HashMap<>();
            if (rawHeaders != null) {
                for (Map.Entry<String, List<String>> entry : rawHeaders.entrySet()) {
                    if (entry.getKey() != null) { // 过滤null key
                        cleanHeaders.put(entry.getKey(), entry.getValue());
                    }
                }
            }
            attempt.setResponseHeaders(cleanHeaders);

            // 获取内容类型和长度
            attempt.setContentType(connection.getContentType());
            attempt.setContentLength(connection.getContentLengthLong());

            // 判断是否成功
            if (responseCode >= 200 && responseCode < 400) {
                attempt.setSuccess(true);

                // 如果是GET请求且成功，尝试读取少量内容
                if ("GET".equals(method)) {
                    try (InputStream is = connection.getInputStream()) {
                        byte[] buffer = new byte[1024];
                        int bytesRead = is.read(buffer);
                        if (bytesRead > 0) {
                            attempt.setContentPreview(new String(buffer, 0, Math.min(bytesRead, 100)));
                        }
                    } catch (Exception e) {
                        attempt.setError("读取内容预览失败: " + e.getMessage());
                    }
                }
            } else {
                attempt.setSuccess(false);

                // 尝试读取错误响应
                try (InputStream errorStream = connection.getErrorStream()) {
                    if (errorStream != null) {
                        byte[] buffer = new byte[1024];
                        int bytesRead = errorStream.read(buffer);
                        if (bytesRead > 0) {
                            attempt.setErrorResponse(new String(buffer, 0, Math.min(bytesRead, 500)));
                        }
                    }
                } catch (Exception e) {
                    // 忽略错误响应读取失败
                }
            }

        } catch (Exception e) {
            attempt.setSuccess(false);
            attempt.setError("连接失败: " + e.getMessage());
            log.debug("测试下载失败: {} - {}", url, e.getMessage());
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }

        return attempt;
    }

    /**
     * 设置详细的HTTP请求头
     */
    private static void setupDetailedHeaders(HttpURLConnection connection, String userAgent) {
        // 基本请求头
        connection.setRequestProperty("User-Agent", userAgent);
        connection.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7");
        connection.setRequestProperty("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
        connection.setRequestProperty("Accept-Encoding", "gzip, deflate");
        connection.setRequestProperty("Connection", "keep-alive");

        // 缓存控制
        connection.setRequestProperty("Cache-Control", "no-cache");
        connection.setRequestProperty("Pragma", "no-cache");

        // 安全相关
        connection.setRequestProperty("Upgrade-Insecure-Requests", "1");
        connection.setRequestProperty("Sec-Fetch-Dest", "document");
        connection.setRequestProperty("Sec-Fetch-Mode", "navigate");
        connection.setRequestProperty("Sec-Fetch-Site", "none");
        connection.setRequestProperty("Sec-Fetch-User", "?1");

        // 可能需要的其他头
        connection.setRequestProperty("DNT", "1");
        connection.setRequestProperty("X-Requested-With", "XMLHttpRequest");

        // 针对某些文件服务的特殊头
        connection.setRequestProperty("Referer", "http://e.cqm.cn/");
        connection.setRequestProperty("Origin", "http://e.cqm.cn");

        // 支持重定向
        connection.setInstanceFollowRedirects(true);
        connection.setDoInput(true);
        connection.setDoOutput(false);
    }

    /**
     * 获取请求头信息
     */
    private static Map<String, String> getRequestHeaders(HttpURLConnection connection) {
        Map<String, String> headers = new HashMap<>();
        // 注意：HttpURLConnection不直接提供获取所有请求头的方法
        // 这里只能记录我们设置的关键头
        headers.put("User-Agent", connection.getRequestProperty("User-Agent"));
        headers.put("Accept", connection.getRequestProperty("Accept"));
        headers.put("Accept-Language", connection.getRequestProperty("Accept-Language"));
        return headers;
    }

    /**
     * 清理URL
     */
    private static String cleanUrl(String url) {
        if (StringUtils.isBlank(url)) {
            return url;
        }

        String cleanedUrl = url.trim();

        // 移除可能的前缀符号
        if (cleanedUrl.startsWith("@")) {
            cleanedUrl = cleanedUrl.substring(1);
        }
        if (cleanedUrl.startsWith("#")) {
            cleanedUrl = cleanedUrl.substring(1);
        }

        // 确保URL以http://或https://开头
        if (!cleanedUrl.toLowerCase().startsWith("http://") &&
                !cleanedUrl.toLowerCase().startsWith("https://")) {
            cleanedUrl = "http://" + cleanedUrl;
        }

        return cleanedUrl;
    }

    /**
     * 诊断结果类
     */
    public static class DiagnosticResult {
        private String originalUrl;
        private String cleanedUrl;
        private String host;
        private int port;
        private String path;
        private String query;
        private String error;
        private String recommendedUserAgent;
        private List<DiagnosticAttempt> attempts = new ArrayList<>();

        // Getters and Setters
        public String getOriginalUrl() {
            return originalUrl;
        }

        public void setOriginalUrl(String originalUrl) {
            this.originalUrl = originalUrl;
        }

        public String getCleanedUrl() {
            return cleanedUrl;
        }

        public void setCleanedUrl(String cleanedUrl) {
            this.cleanedUrl = cleanedUrl;
        }

        public String getHost() {
            return host;
        }

        public void setHost(String host) {
            this.host = host;
        }

        public int getPort() {
            return port;
        }

        public void setPort(int port) {
            this.port = port;
        }

        public String getPath() {
            return path;
        }

        public void setPath(String path) {
            this.path = path;
        }

        public String getQuery() {
            return query;
        }

        public void setQuery(String query) {
            this.query = query;
        }

        public String getError() {
            return error;
        }

        public void setError(String error) {
            this.error = error;
        }

        public String getRecommendedUserAgent() {
            return recommendedUserAgent;
        }

        public void setRecommendedUserAgent(String recommendedUserAgent) {
            this.recommendedUserAgent = recommendedUserAgent;
        }

        public List<DiagnosticAttempt> getAttempts() {
            return attempts;
        }

        public void addAttempt(DiagnosticAttempt attempt) {
            this.attempts.add(attempt);
        }

        public boolean hasSuccessfulAttempt() {
            return attempts.stream().anyMatch(DiagnosticAttempt::isSuccess);
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("诊断结果:\n");
            sb.append("原始URL: ").append(originalUrl).append("\n");
            sb.append("清理后URL: ").append(cleanedUrl).append("\n");
            sb.append("主机: ").append(host).append("\n");
            sb.append("路径: ").append(path).append("\n");
            sb.append("查询参数: ").append(query).append("\n");

            if (error != null) {
                sb.append("错误: ").append(error).append("\n");
            }

            if (recommendedUserAgent != null) {
                sb.append("推荐User-Agent: ").append(recommendedUserAgent).append("\n");
            }

            sb.append("\n尝试记录:\n");
            for (int i = 0; i < attempts.size(); i++) {
                sb.append("尝试 ").append(i + 1).append(": ").append(attempts.get(i)).append("\n");
            }

            return sb.toString();
        }
    }

    /**
     * 诊断尝试类
     */
    public static class DiagnosticAttempt {
        private String method;
        private String userAgent;
        private boolean success;
        private int responseCode;
        private String responseMessage;
        private long responseTime;
        private String contentType;
        private long contentLength;
        private String error;
        private String contentPreview;
        private String errorResponse;
        private Map<String, String> requestHeaders;
        private Map<String, List<String>> responseHeaders;

        // Getters and Setters
        public String getMethod() {
            return method;
        }

        public void setMethod(String method) {
            this.method = method;
        }

        public String getUserAgent() {
            return userAgent;
        }

        public void setUserAgent(String userAgent) {
            this.userAgent = userAgent;
        }

        public boolean isSuccess() {
            return success;
        }

        public void setSuccess(boolean success) {
            this.success = success;
        }

        public int getResponseCode() {
            return responseCode;
        }

        public void setResponseCode(int responseCode) {
            this.responseCode = responseCode;
        }

        public String getResponseMessage() {
            return responseMessage;
        }

        public void setResponseMessage(String responseMessage) {
            this.responseMessage = responseMessage;
        }

        public long getResponseTime() {
            return responseTime;
        }

        public void setResponseTime(long responseTime) {
            this.responseTime = responseTime;
        }

        public String getContentType() {
            return contentType;
        }

        public void setContentType(String contentType) {
            this.contentType = contentType;
        }

        public long getContentLength() {
            return contentLength;
        }

        public void setContentLength(long contentLength) {
            this.contentLength = contentLength;
        }

        public String getError() {
            return error;
        }

        public void setError(String error) {
            this.error = error;
        }

        public String getContentPreview() {
            return contentPreview;
        }

        public void setContentPreview(String contentPreview) {
            this.contentPreview = contentPreview;
        }

        public String getErrorResponse() {
            return errorResponse;
        }

        public void setErrorResponse(String errorResponse) {
            this.errorResponse = errorResponse;
        }

        public Map<String, String> getRequestHeaders() {
            return requestHeaders;
        }

        public void setRequestHeaders(Map<String, String> requestHeaders) {
            this.requestHeaders = requestHeaders;
        }

        public Map<String, List<String>> getResponseHeaders() {
            return responseHeaders;
        }

        public void setResponseHeaders(Map<String, List<String>> responseHeaders) {
            this.responseHeaders = responseHeaders;
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(method).append(" - ");
            if (success) {
                sb.append("成功 (").append(responseCode).append(") ");
                sb.append("耗时: ").append(responseTime).append("ms ");
                if (contentType != null) {
                    sb.append("类型: ").append(contentType).append(" ");
                }
                if (contentLength > 0) {
                    sb.append("大小: ").append(contentLength).append("字节");
                }
            } else {
                sb.append("失败 (").append(responseCode).append(") ");
                if (error != null) {
                    sb.append("错误: ").append(error);
                }
                if (errorResponse != null) {
                    sb.append(" 响应: ").append(errorResponse.substring(0, Math.min(errorResponse.length(), 100)));
                }
            }
            return sb.toString();
        }
    }
} 